package com.xindao.xml;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;

import org.xmlpull.v1.XmlSerializer;

import android.util.Base64;
import android.util.Xml;

public class XmlBuilder {

	public static void buildXml(OutputStream outs, String encoding, Object obj)
			throws IllegalArgumentException, IllegalStateException,
			IOException, IllegalAccessException {
		XmlSerializer serializer = Xml.newSerializer(); // ����һ��Xml���л�
		serializer.setOutput(outs, encoding); // ������������ַ����
		serializer.startDocument(encoding, true); // ��ʼ�ĵ�
		writeXml(serializer, obj); // д�ĵ�
		serializer.endDocument(); // �����ĵ�
		outs.close(); // �ر������
	}

	private static void writeXml(XmlSerializer serializer, Object obj)
			throws IllegalArgumentException, IllegalStateException,
			IOException, IllegalAccessException {

		final String tag_type = "type";
		final String tag_value = "value";

		Class<?> cls = obj.getClass(); // ��ȡ��������ʱ��
		String clsName = cls.getName(); // ��ȡ�������

		serializer.startTag(null, clsName);

		Field[] fields = cls.getDeclaredFields(); // �����������������ֶ�

		boolean isWrite;
		Class<?> type; // ��������
		String varName, typeName, value = null; // ���������������ֵ
		for (Field field : fields) {
			isWrite = true;
			type = field.getType(); // ��ȡ��������
			typeName = type.getName(); // ��ȡ������
			field.setAccessible(true); // ���ñ����ɷ���
			if (type.isPrimitive()) { // �Ƿ�Ϊ������
				if (typeName.equals("boolean")) {
					value = String.valueOf(field.getBoolean(obj));
				} else if (typeName.equals("char")) {
					// char��δ��ֵ��ΪĬ��'\u0000'ʱ����Ӱ��parser.next()
					char c = field.getChar(obj);
					value = c == '\u0000' ? "null" : String.valueOf(field
							.getChar(obj));
				} else if (typeName.equals("byte")) {
					value = String.valueOf(field.getByte(obj));
				} else if (typeName.equals("short")) {
					value = String.valueOf(field.getShort(obj));
				} else if (typeName.equals("int")) {
					value = String.valueOf(field.getInt(obj));
				} else if (typeName.equals("long")) {
					value = String.valueOf(field.getLong(obj));
				} else if (typeName.equals("float")) {
					value = String.valueOf(field.getFloat(obj));
				} else if (typeName.equals("double")) {
					value = String.valueOf(field.getDouble(obj));
				}
			} else if (typeName.equals("java.lang.String")) { // �Ƿ�ΪString
				value = field.get(obj) == null ? "null" : field.get(obj)
						.toString();
			} else if (typeName.equals("[B")) { // �Ƿ�Ϊbyte[]
				typeName = getTypeHelper(type); // �ַ����->[]��ʽ
				// ��Base64��byte[]ת���ַ�SDK 2.2֮���Դ�
				value = field.get(obj) == null ? "null"
						: Base64.encodeToString((byte[]) field.get(obj),
								Base64.DEFAULT);
			} else { // ���������ݲ���Ҫ
				isWrite = false;
			}
			if (isWrite) {
				varName = field.getName(); // ��ȡ������
				serializer.startTag(null, varName);
				writeTag(serializer, tag_type, typeName);
				writeTag(serializer, tag_value, value);
				serializer.endTag(null, varName);
			}
		}

		serializer.endTag(null, clsName);
	}

	private static String getTypeHelper(Class<?> type) {
		if (type.isArray()) {
			Class<?> c = type.getComponentType();
			return getTypeHelper(c) + "[]";
		} else {
			return type.getName();
		}
	}

	private static void writeTag(XmlSerializer serializer, String tag, String value)
			throws IllegalArgumentException, IllegalStateException, IOException {
		serializer.startTag(null, tag);
		serializer.text(value);
		serializer.endTag(null, tag);
	}

}